import { MenuType, type MenuInfo } from "@/models";
import { PermissionModeEnum } from "@/models/enums/app";
import { default as ProjectSetting, default as projectSetting } from "@/settings/project";
import { filter } from "@/utils";
import { cloneDeep } from "lodash-es";
import { defineStore } from "pinia";
import { computed, reactive, toRefs } from "vue";
import type { RouteRecordRaw } from "vue-router";
import { store } from ".";

interface PermissionState {
  /** 路由是否动态添加 */ added: boolean;
  // /** 路由列表 */ routes: RouteRecordRaw[];
  /** 菜单列表 */ tree: MenuInfo[];
  flat: MenuInfo[];
}

export const usePermissionStore = defineStore("app-permission", () => {
  //#region [state]
  const state = reactive<PermissionState>({
    added: false,
    tree: [],
    flat: [],
  });
  const { permissionMode = projectSetting.permissionMode } = ProjectSetting;
  //#endregion

  //#region [getters]
  const isAdded = computed(() => state.added);
  const menus = computed(() => state.tree);
  const source = computed(() => state.flat);
  //#endregion

  //#region [action]
  /** 设置是否动态设置路由状态 */
  const setAdded = (added: boolean) => {
    state.added = added;
  };

  /** 设置菜单 */
  const setMenus = (menus: MenuInfo[]) => {
    // state.tree = listToTree(cloneDeep(menus));

    const _menus = cloneDeep(menus).sort((a, b) => (a.sortId || 0) - (b.sortId || 0));
    for (const menu of _menus) {
      const parent = _menus.find((p) => p.id === menu.pid);
      if (!parent) {
        menu.pid = undefined;
        continue;
      }

      if (menu.type === MenuType.功能) {
        if (!parent.actions) parent.actions = [];
        if (!parent.actions.includes(menu)) parent.actions.push(menu);
      } else {
        if (!parent.children) parent.children = [];
        if (!parent.children.includes(menu)) parent.children.push(menu);
      }
    }

    state.tree = _menus.filter((r) => !r.pid);
    state.flat = _menus;
  };

  /** 构建路由 */
  const buildRoutes = async () => {
    let routes: RouteRecordRaw[] = [];

    /** 授权路由过滤器 */
    const routeFilter = (route: RouteRecordRaw) => {
      return state.flat.some((m) => m.code === route.name);
    };

    /** 移除排除项目 */
    const routeRemoveIgnoreFilter = (route: RouteRecordRaw) => {
      const { meta } = route;
      // ignoreRoute 为true 则路由仅用于菜单生成，不会在实际的路由表中出现
      const { ignoreRoute } = meta || {};
      // arr.filter 返回 true 表示该元素通过测试
      return !ignoreRoute;
    };

    switch (permissionMode) {
      case PermissionModeEnum.ROLE:
        // 对非一级路由进行过滤
        routes = filter(routes, routeFilter);
        // 对一级路由根据角色权限过滤
        routes = routes.filter(routeFilter);
        break;
      case PermissionModeEnum.ROUTE_MAPPING:
        // 对非一级路由进行过滤
        routes = filter(routes, routeFilter);
        // 对一级路由再次根据角色权限过滤
        routes = routes.filter(routeFilter);
        // 移除掉 ignoreRoute: true 的路由 非一级路由
        routes = filter(routes, routeRemoveIgnoreFilter);
        // 移除掉 ignoreRoute: true 的路由 一级路由；
        routes = routes.filter(routeRemoveIgnoreFilter);
        // 对菜单进行排序
        routes.sort((a, b) => {
          let aa = 0,
            bb = 0;
          if (a.meta && typeof a.meta?.orderNo === "number") aa = a.meta.orderNo;
          if (b.meta && typeof b.meta?.orderNo === "number") bb = b.meta.orderNo;
          return aa - bb;
        });

        // 设置菜单列表
        // setRoutes(routes);
        break;
      case PermissionModeEnum.BACK:
        break;
    }

    return routes;
  };

  /** 重置所有状态 */
  const resetState = () => {
    state.added = false;
    state.tree = [];
    state.flat = [];
  };
  //#endregion

  return {
    ...toRefs(state),
    isAdded,
    menus,
    source,
    setAdded,
    setMenus,
    buildRoutes,
    resetState,
  };
});

/**
 * @description 权限 (在setup方法外使用此方法)
 */
export function usePermissionStoreWithOut() {
  return usePermissionStore(store);
}
